use serde::{Serialize, Serializer};
use std::{collections::HashMap, sync::Mutex};
use tauri::{command, AppHandle, Runtime, State, Window};

use model_graph_types::{
    connector::{Connector, ExecuteOptions, QueryOptions},
    database::{DataSource, DatabaseType},
    modeling::Value,
};
use serde_json::Value as JsonValue;
use union_connector::UnionConnector;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error(transparent)]
    Anyhow(#[from] anyhow::Error),
}

impl Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.to_string().as_ref())
    }
}

type Result<T> = std::result::Result<T, Error>;

#[derive(Default)]
pub struct ContextState(Mutex<HashMap<String, UnionConnector>>);

#[command]
pub async fn open<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    data_source: DataSource,
) -> Result<bool> {
    //检测改data_source是否存在
    let insert = {
        let map = state
            .0
            .lock()
            .map_err(|err| anyhow::anyhow!("获取锁失败！"))?;

        if map.contains_key(&data_source.url) {
            true
        } else {
            false
        }
    };
    if !insert {
        //
        let connector = UnionConnector::open(&data_source).await?;

        state
            .0
            .lock()
            .map_err(|err| anyhow::anyhow!("获取锁失败！"))?
            .insert(data_source.url.clone(), connector);
    }

    Ok(true)
}

#[command]
pub async fn close<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    data_source: DataSource,
) -> Result<bool> {
    Ok(true)
}

#[command]
pub async fn query<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    data_source: DataSource,
    sql: String,
    args: Vec<JsonValue>,
    options: QueryOptions,
) -> Result<(Vec<JsonValue>, Vec<JsonValue>)> {
    // let map = state
    //     .0
    //     .lock()
    //     .map_err(|err| anyhow::anyhow!("获取锁失败！"))?;

    // let connector = map.get(&data_source.url).map_or(
    //     Err(Error::Anyhow(anyhow::anyhow!("没有找到Connector"))),
    //     |v| Ok(v),
    // )?;
    let mut argsv = vec![];
    for r in args {
        argsv.push(Value::try_from(r.clone())?);
    }

    let connector = UnionConnector::open(&data_source).await?;
    //
    tracing::debug!("连接数据源成功!");

    let result = connector.query(&sql, &argsv, options).await;

    match result {
        Ok((header, body)) => {
            let mut data = vec![];
            let mut columns = vec![];
            for r in body {
                data.push(r.try_into()?);
            }
            for r in header {
                columns.push(r.try_into()?);
            }
            tracing::debug!("执行成功!");
            Ok((columns, data))
        }
        Err(err) => {
            tracing::error!("执行失败:{}", err);
            Err(Error::Anyhow(err))
        }
    }
}

#[command]
pub async fn query_one<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    data_source: DataSource,
    sql: String,
    args: Vec<JsonValue>,
    options: QueryOptions,
) -> Result<(Vec<JsonValue>, JsonValue)> {
    // let map = state
    //     .0
    //     .lock()
    //     .map_err(|err| anyhow::anyhow!("获取锁失败！"))?;

    // let connector = map.get(&data_source.url).map_or(
    //     Err(Error::Anyhow(anyhow::anyhow!("没有找到Connector"))),
    //     |v| Ok(v),
    // )?;

    let mut argsv = vec![];
    for r in args {
        argsv.push(Value::try_from(r.clone())?);
    }

    let connector = UnionConnector::open(&data_source).await?;
    //
    tracing::debug!("连接数据源成功!");

    let result = connector.query_one(&sql, &argsv, options).await;

    match result {
        Ok((header, data)) => {
            let mut columns = vec![];
            for r in header {
                columns.push(r.try_into()?);
            }
            tracing::debug!("执行成功!");
            Ok((columns, data.try_into()?))
        }
        Err(err) => {
            tracing::error!("执行失败:{}", err);
            Err(Error::Anyhow(err))
        }
    }
}

#[command]
pub async fn execute<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    data_source: DataSource,
    sql: String,
    args: Vec<JsonValue>,
    options: ExecuteOptions,
) -> Result<String> {
    // let res = connector.execute(&sql, &argsv, options).await?;
    // let connector = {
    //     let map = state
    //         .0
    //         .lock()
    //         .map_err(|err| anyhow::anyhow!("获取锁失败！"))?;

    //     // let connector = map.get(&data_source.url.clone()).map_or(
    //     //     Err(Error::Anyhow(anyhow::anyhow!("没有找到Connector"))),
    //     //     |v| Ok(v.clone()),
    //     // )?;

    //     UnionConnector::open(&data_source).await?
    // };

    let mut argsv = vec![];

    for r in args {
        argsv.push(Value::try_from(r.clone())?);
    }
    let connector = UnionConnector::open(&data_source).await?;
    //
    tracing::debug!("连接数据源成功!");

    let result = connector.execute(&sql, &argsv, options).await;

    match result {
        Ok(res) => {
            tracing::debug!("执行成功!");
            Ok(format!("{}", res))
        }
        Err(err) => {
            tracing::error!("执行失败:{}", err);
            Err(Error::Anyhow(err))
        }
    }
}
